﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel.Composition;

using NuMetaheuristics;
using NuMetaheuristics.Genotypes;

namespace NuMetaheuristics.Operators.Vector
{
    /// <summary>
    /// Bound each element of a vector within the given bounds.
    /// </summary>
    [DataContract(Namespace = "http://numetaheuristics.codeplex.com/schemas")]
    [Export(typeof(IUnaryOperator<DoubleVectorGenotype>))]
    public class DoubleVectorBounding : IUnaryOperator<DoubleVectorGenotype>
    {
        [DataMember]
        private double _min;
        [DataMember]
        private double _max;

        public DoubleVectorBounding()
        {
        }

        public DoubleVectorBounding(double min, double max)
        {
            _min = min;
            _max = max;
        }

        public bool IsBounded(DoubleVectorGenotype operand)
        {
            foreach (double x in operand.Vector)
            {
                if (x < _min || x > _max)
                    return false;
            }
            return true;
        }

        public void Operate(ref DoubleVectorGenotype operand)
        {
            if (operand == null)
                throw new ArgumentNullException();

            for (int i = 0; i < operand.Vector.Length; i++)
            {
                if (operand.Vector[i] < _min)
                {
                    operand.Vector[i] = _min;
                }
                else if (operand.Vector[i] > _max)
                {
                    operand.Vector[i] = _max;
                }

            }
        }
    }

    /// <summary>
    /// Bound each element of a vector within the given bounds.
    /// </summary>
    [DataContract(Namespace = "http://numetaheuristics.codeplex.com/schemas")]
    [Export(typeof(IUnaryOperator<IntegerVectorGenotype>))]
    public class IntegerVectorBounding : IUnaryOperator<IntegerVectorGenotype>
    {
        [DataMember]
        private int _min;
        [DataMember]
        private int _max;

        public IntegerVectorBounding()
        {
        }

        public IntegerVectorBounding(int min, int max)
        {
            _min = min;
            _max = max;
        }

        public bool IsBounded(IntegerVectorGenotype operand)
        {
            foreach (double x in operand.Vector)
            {
                if (x < _min || x > _max)
                    return false;
            }
            return true;
        }

        public void Operate(ref IntegerVectorGenotype operand)
        {
            if (operand == null)
                throw new ArgumentNullException();

            for (int i = 0; i < operand.Vector.Length; i++)
            {
                if (operand.Vector[i] < _min)
                {
                    operand.Vector[i] = _min;
                }
                else if (operand.Vector[i] > _max)
                {
                    operand.Vector[i] = _max;
                }

            }
        }
    }
}
